// UDP hop - port hopping for better NAT traversal

use std::net::SocketAddr;
use std::time::Duration;
use tokio::net::UdpSocket;
use tokio::time::interval;
use tracing::debug;

pub struct UdpHop {
    sockets: Vec<UdpSocket>,
    current_index: usize,
    hop_interval: Duration,
}

impl UdpHop {
    pub async fn new(bind_addr: SocketAddr, num_ports: usize, hop_interval: Duration) -> std::io::Result<Self> {
        let mut sockets = Vec::new();
        
        for _ in 0..num_ports {
            let socket = UdpSocket::bind(bind_addr).await?;
            sockets.push(socket);
        }
        
        Ok(Self {
            sockets,
            current_index: 0,
            hop_interval,
        })
    }

    pub async fn run(&mut self) {
        let mut ticker = interval(self.hop_interval);
        
        loop {
            ticker.tick().await;
            self.hop();
        }
    }

    fn hop(&mut self) {
        self.current_index = (self.current_index + 1) % self.sockets.len();
        debug!("UDP hop: switched to socket {}", self.current_index);
    }

    pub fn current_socket(&self) -> &UdpSocket {
        &self.sockets[self.current_index]
    }

    pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> std::io::Result<usize> {
        self.current_socket().send_to(buf, target).await
    }

    pub async fn recv_from(&self, buf: &mut [u8]) -> std::io::Result<(usize, SocketAddr)> {
        self.current_socket().recv_from(buf).await
    }
}
